package com.zxjbyte.yiyi.framework.common.core.excel;

import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.google.common.collect.Lists;
import com.zxjbyte.yiyi.framework.common.util.ImageCompressUtil;
import com.zxjbyte.yiyi.framework.common.util.OkHttpUtil;
import com.zxjbyte.yiyi.framework.common.util.URLXUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.util.Units;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * EasyExcel 支持将多个图片导出到同一个 Excel 单元格中
 * 且根据图片宽高，自适应修改列宽，行高
 * @Author zhangxingjia
 * @Date 2025/10/13 11:54
 * @Version: 1.0
 */
@Slf4j
public class MultipleImageWriteStrategy implements CellWriteHandler {

    // 固定单元格高度（像素）
    private static final int FIXED_CELL_HEIGHT = 50;
    // 常量定义
    public static final double PIXELS_PER_POINT = 96.0 / 72.0; // 1.3333...
    public static final double CHAR_WIDTH_PIXELS = 7.0;
    public static final double COLUMN_PADDING_PIXELS = 5.0;

    // 需要处理的图片列索引
    private final List<Integer> imageColumnIndexList;

    public MultipleImageWriteStrategy(List<Integer> imageColumnIndexList) {
        this.imageColumnIndexList = imageColumnIndexList;
    }

    @Override
    public void afterCellDispose(CellWriteHandlerContext context) {
        // 只在数据行处理，排除表头
        if(context.getHead()){
            return;
        }
        Integer columnIndex = context.getColumnIndex();
        if(imageColumnIndexList != null && imageColumnIndexList.contains(columnIndex)){
            WriteCellData<?> writeCellData = context.getCellDataList().get(0);
            String stringValue;
            if(writeCellData != null && StrUtil.isNotEmpty(stringValue = writeCellData.getStringValue())){
                writeImagesToCell(context.getWriteSheetHolder(), context.getCell(), stringValue);
            }
        }
    }



    /**
     * 将多个图片写入单元格
     */
    private void writeImagesToCell(WriteSheetHolder writeSheetHolder, Cell cell, String stringValue) {
        List<String> urlList = StrUtil.splitTrim(stringValue, ",");
        if(urlList.stream().anyMatch(f -> !URLXUtil.isValidURL(f))){
            return;
        }
        try {
            // 清空原有文本内容
            cell.setCellValue("");
            drawImagesToCell(writeSheetHolder, cell, urlList);
        } catch (Exception e) {
            // 如果图片处理失败，保留原始文本
            cell.setCellValue(stringValue);
            log.info(">>> 图片处理失败或者非图片时：{}", e.getMessage());
        }
    }



    /**
     * 绘制图片到单元格
     */
    private void drawImagesToCell(WriteSheetHolder writeSheetHolder, Cell cell, List<String> imageUrls) throws IOException {

        Sheet sheet = writeSheetHolder.getSheet();
        Drawing<?> drawing = sheet.createDrawingPatriarch();

        // 获取单元格位置和尺寸
        int rowIndex = cell.getRowIndex();
        int colIndex = cell.getColumnIndex();

        // 计算图片在单元格中的位置和大小
        int horizontalSpacing = 5; // 图片水平间距

        // 记录当前水平位置
        int currentLeftMargin = 0;

        int maxImageWidth = 0;

        // 分离图片URL和非图片URL
        List<String> imageUrlList = Lists.newArrayList();
        List<String> nonImageUrlList = Lists.newArrayList();
        for (String imageUrl : imageUrls) {
            if (URLXUtil.isImageUrl(imageUrl)) {
                imageUrlList.add(imageUrl);
            } else {
                nonImageUrlList.add(imageUrl);
            }
        }

        // 如果只有非图片URL，没有图片URL，直接返回，在单元格中显示文本
        if (!nonImageUrlList.isEmpty() && imageUrlList.isEmpty()) {
            throw new IOException("非图片时保留原始文本");
        }

        // 批量并发下载图片
        List<byte[]> imageBytes = downloadImagesConcurrent(imageUrlList);

        // 处理图片URL
        for (int i = 0; i < imageUrlList.size(); i++) {
            String imageUrl = imageUrlList.get(i);
            byte[] imageData = imageBytes.get(i);

            if (imageData != null) {
                try {
                    // 读取图片尺寸
                    BufferedImage image = ImgUtil.toImage(imageData);
                    int originalWidth = image.getWidth();
                    int originalHeight = image.getHeight();
                    // 根据固定高度计算宽度（保持宽高比）
                    int imageWidth = calculateWidthByFixedHeight(originalWidth, originalHeight);

                    // 创建锚点
                    Workbook workbook = sheet.getWorkbook();
                    ClientAnchor anchor = workbook.getCreationHelper().createClientAnchor();

                    anchor.setCol1(colIndex);
                    anchor.setRow1(rowIndex);
                    anchor.setCol2(colIndex);
                    anchor.setRow2(rowIndex);
                    anchor.setDx1(currentLeftMargin * Units.EMU_PER_PIXEL);
                    anchor.setDy1(0);  // 图片从顶部开始
                    anchor.setDx2((currentLeftMargin + imageWidth) * Units.EMU_PER_PIXEL);
                    anchor.setDy2(FIXED_CELL_HEIGHT * Units.EMU_PER_PIXEL);

                    // 插入图片
                    int pictureIndex = workbook.addPicture(imageData, Workbook.PICTURE_TYPE_JPEG);

                    drawing.createPicture(anchor, pictureIndex);
                    // 更新水平位置，为下一张图片准备
                    currentLeftMargin += imageWidth + horizontalSpacing;

                    maxImageWidth += imageWidth;
                } catch (Exception e) {
                    // 图片处理异常，将该URL添加到非图片列表
                    log.error("处理图片失败: {}, 错误: {}", imageUrl, e.getMessage(), e);
                    nonImageUrlList.add(imageUrl);
                }
            } else {
                // 图片下载失败，将该URL添加到非图片列表
                nonImageUrlList.add(imageUrl);
            }
        }

        // 如果有非图片URL，更新单元格文本（包含原有的非图片URL和处理失败的图片URL）
        String nonImageText = null;
        if (!nonImageUrlList.isEmpty()) {
            nonImageText = String.join(",", nonImageUrlList);
            cell.setCellValue(nonImageText);

            // 设置单元格垂直对齐为底部对齐，确保文本显示在底部
            CellStyle cellStyle = sheet.getWorkbook().createCellStyle();
            cellStyle.setVerticalAlignment(VerticalAlignment.BOTTOM);
            cell.setCellStyle(cellStyle);
        }

        // 调整行高以适应图片
        Row row = sheet.getRow(rowIndex);
        if (row != null && !imageUrlList.isEmpty()) {
            int totalHeightPixels = FIXED_CELL_HEIGHT;
            if (nonImageText != null) {
                totalHeightPixels += 20; //  + 间距
            }
            row.setHeightInPoints(pixelsToPoiRowHeight(totalHeightPixels));
        }

        // 条件列宽
        if (!imageUrlList.isEmpty()) {
            int columnWidth = pixelsToPoiColumnWidth(maxImageWidth);
            int maxColumnWidth = sheet.getColumnWidth(colIndex);
            if (columnWidth > maxColumnWidth) {
                sheet.setColumnWidth(colIndex, columnWidth);
            }
        }
    }

    /**
     * 批量并发下载
     * @param imageUrlList
     * @return
     */
    public List<byte[]> downloadImagesConcurrent(List<String> imageUrlList) {
        List<CompletableFuture<byte[]>> futures = imageUrlList.stream()
            .map(url -> CompletableFuture.supplyAsync(() -> downloadImage(url)))
            .collect(Collectors.toList());
        return futures.stream()
            .map(CompletableFuture::join)
            .collect(Collectors.toList());
    }

    /**
     * 从URL下载图片并转换为字节数组
     */
    private byte[] downloadImage(String imageUrl) {
        try {
            byte[] bytes = OkHttpUtil.downloadAsBytes(imageUrl);
            String fileName = cn.hutool.core.io.FileUtil.getName(imageUrl);
            return ImageCompressUtil.smartCompressExcelImage(bytes, fileName);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 根据固定高度计算宽度（保持宽高比）
     */
    private int calculateWidthByFixedHeight(int originalWidth, int originalHeight) {
        if (originalHeight == 0) return FIXED_CELL_HEIGHT; // 默认宽度

        // 计算宽高比，根据固定高度计算宽度
        double aspectRatio = (double) originalWidth / originalHeight;
        return (int) (FIXED_CELL_HEIGHT * aspectRatio);
    }


    /**
     * 像素转为 Apache POI 的列宽单位
     * @param pixels 像素值
     * @return POI 的列宽单位 (1/256 字符宽度)
     */
    public static int pixelsToPoiColumnWidth(int pixels) {
        double excelCharWidth = (pixels - COLUMN_PADDING_PIXELS) / CHAR_WIDTH_PIXELS;
        return (int) (excelCharWidth * 256);
    }

    /**
     * 像素转为行高 (单位: 磅)
     * @param pixels 像素值
     * @return 磅值，可直接用于 row.setHeightInPoints()
     */
    public static float pixelsToPoiRowHeight(int pixels) {
        return (float) (pixels / PIXELS_PER_POINT);
    }

}
